

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>

#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int connfd;

void sig_urg(int signo);

int use_select(int connection_fd);

// build : gcc -Wall -Wshadow -g urg_server.c -o urg_server
int main(int argc, char * argv[]) {

    if (argc < 2) {

        printf("need server port\n");
        exit(1);
    }
    uint16_t port  =atoi(argv[1]);
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in sai;
    bzero(&sai, sizeof(sai));

    sai.sin_family = AF_INET;
    sai.sin_port   = htons(port);
    sai.sin_addr.s_addr = htonl(INADDR_ANY);
    
    bind(server_fd, (struct sockaddr * )&sai, sizeof(sai));


    listen(server_fd, 10);

    connfd = accept(server_fd, NULL, NULL);

    use_select(connfd);

    // use signal 
    // signal(SIGURG, sig_urg);

    // fcntl(connfd, F_SETOWN, getpid());

    // char buffer[1024];
    // int  n = 0;
    // for (; ; ) {

    //     bzero(buffer, 1024);
    //     if ((n = recv(connfd, buffer, 1024, 0)) == 0) {

    //         printf("recevice EOF\n");
    //         break;
    //     }
    //     buffer[n] = '\0';
    //     printf("read %d bytes: %s\n", n, buffer);
    // }

    close(server_fd);
    close(connfd);
    return EXIT_SUCCESS;
}

void sig_urg(int signo) {

    int n;
    char buffer[1024];

    printf("SIGURG receviceed\n");
    n = recv(connfd, buffer, 1024 - 1, MSG_OOB);
    buffer[n] = '\0';
    printf("read %d oob byte: %s\n", n, buffer);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int use_select(int connection_fd) {

    fd_set  read_set, exception_set;
    FD_ZERO(&read_set);
    FD_ZERO(&exception_set);

    char buffer[1024];
    int just_read_oob = 0;

    for (; ; ) {

        bzero(buffer, 1024);

        FD_SET(connfd, &read_set);
        if (just_read_oob == 0) {

            FD_SET(connfd, &exception_set);
        }
        select(connfd + 1, &read_set, NULL, &exception_set, NULL);

        if (FD_ISSET(connfd, &exception_set)) {

            int n = recv(connfd, buffer, 1024, MSG_OOB);
            buffer[n] = '\0';

            printf("read %d oob byte : %s\n", n, buffer);
            just_read_oob = 1;

            FD_CLR(connfd, &exception_set);
        }
        if (FD_ISSET(connfd, &read_set)) {

            int n = 0;
            if ((n = read(connfd, buffer, 1024)) == 0) {

                printf("recevice EOF\n");
                break;
            }
            buffer[n] = '\0';
            printf("read %d bytes : %s\n", n, buffer);
            just_read_oob = 0;
        }
    }
    return (0);
}